from flask import Blueprint, request, jsonify, make_response, Response
from app.models.database import db, Scan, Vulnerability, TaskStatus, TargetRange, Schedule
from app.services.scan_service import ScanService, create_mock_scan, AttackPathAnalyzer
from app.services.target_range_service import TargetRangeService
from app.services.schedule_service import ScheduleService
from app.services.report_service import ReportService
from app.services.internal_target_range import InternalTargetRangeService
from app.services.vulnerability_stats_service import VulnerabilityStatsService
from app.services.vulnerability_script_manager import script_manager
from app.services.risk_assessment import RiskAssessmentService
from app.utils.logger import logger
from app.utils.redis_config import get_cached_scan_result, get_scan_progress, is_redis_available, cache_scan_result
from datetime import datetime
from sqlalchemy import text
import os
import tempfile

# 创建风险评估服务实例
risk_assessment_service = RiskAssessmentService()



# 攻击路径分析器实例
attack_path_analyzer = AttackPathAnalyzer()

# 创建API蓝图
api_bp = Blueprint('api', __name__)

@api_bp.route('/scan', methods=['POST'])
def submit_scan():
    """提交扫描任务"""
    try:
        # 获取请求数据
        data = request.json
        target = data.get('target')
        scan_depth = data.get('scan_depth', 2)
        scan_types = data.get('scan_types', ['sql_injection', 'xss', 'info_leak'])
        
        # 验证必填字段
        if not target:
            return jsonify({'error': 'Target is required'}), 400
        
        # 使用ScanService提交扫描任务
        scan_service = ScanService()
        scan_data = {
            'target': target,
            'scan_depth': scan_depth,
            'scan_types': scan_types
        }
        scan_id = scan_service.submit_scan(scan_data)
        
        # 获取扫描记录
        scan = Scan.query.get(scan_id)
        if not scan:
            return jsonify({'error': 'Failed to create scan'}), 500
        
        logger.info(f"Scan task created: {scan_id}, target: {target}")
        
        return jsonify({
            'scan_id': scan_id,
            'task_id': scan_id,  # 为了兼容前端，同时返回task_id
            'status': 'pending',
            'created_at': scan.created_at.isoformat()
        }), 202
        
    except Exception as e:
        logger.error(f"Error submitting scan: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/scan/<task_id>/status', methods=['GET'])
def get_scan_status(task_id):
    """获取扫描任务状态"""
    try:
        # 首先查询任务状态获取scan_id
        task_status = TaskStatus.query.filter_by(task_id=task_id).first()
        
        # 如果TaskStatus不存在，尝试创建一个新的
        if not task_status:
            # 假设task_id等于scan_id（根据提交扫描的逻辑）
            scan = Scan.query.get(task_id)
            if not scan:
                return jsonify({'error': 'Scan not found'}), 404
            
            # 创建新的TaskStatus记录
            task_status = TaskStatus(
                task_id=task_id,
                scan_id=task_id,
                status='pending',
                progress=0
            )
            db.session.add(task_status)
            db.session.commit()
            logger.info(f"Created missing TaskStatus for task_id: {task_id}")
        
        scan_id = task_status.scan_id
        
        # 尝试从Redis获取扫描进度（如果可用）
        if is_redis_available():
            redis_progress = get_scan_progress(scan_id)
            if redis_progress:
                # 查询关联的扫描任务获取目标信息
                scan = Scan.query.get(scan_id)
                if not scan:
                    return jsonify({'error': 'Scan not found'}), 404
                
                # 优先返回Redis中的数据
                return jsonify({
                    'task_id': task_id,
                    'scan_id': scan_id,
                    'target': scan.target,
                    'status': redis_progress.get('status', task_status.status),
                    'progress': redis_progress.get('progress', task_status.progress),
                    'created_at': task_status.created_at.isoformat(),
                    'updated_at': redis_progress.get('updated_at', task_status.updated_at.isoformat())
                })
        
        # Redis不可用或缓存未命中，从数据库获取
        scan = Scan.query.get(scan_id)
        if not scan:
            return jsonify({'error': 'Scan not found'}), 404
        
        return jsonify({
            'task_id': task_id,
            'scan_id': scan_id,
            'target': scan.target,
            'status': task_status.status,
            'progress': task_status.progress,
            'created_at': task_status.created_at.isoformat(),
            'updated_at': task_status.updated_at.isoformat()
        })
        
    except Exception as e:
        logger.error(f"Error getting scan status: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/scan/<task_id>/report', methods=['GET'])
def get_scan_report(task_id):
    """获取扫描报告"""
    try:
        # 查询任务状态获取scan_id
        task_status = TaskStatus.query.filter_by(task_id=task_id).first()
        if not task_status:
            return jsonify({'error': 'Task not found'}), 404
        
        scan_id = task_status.scan_id
        
        # 尝试从Redis获取缓存的扫描报告（如果可用）
        if is_redis_available():
            cached_report = get_cached_scan_result(scan_id)
            if cached_report:
                logger.debug(f"从Redis返回缓存的扫描报告: {scan_id}")
                # 优先返回Redis缓存的报告
                return jsonify(cached_report)
        
        # Redis不可用或缓存未命中，从数据库获取
        # 查询关联的扫描任务
        scan = Scan.query.get(scan_id)
        if not scan:
            return jsonify({'error': 'Scan not found'}), 404
        
        # 查询所有漏洞
        vulnerabilities = Vulnerability.query.filter_by(scan_id=scan_id).all()
        vuln_list = [v.to_dict() for v in vulnerabilities]
        
        # 计算风险统计信息
        risk_stats = {
            'total': len(vulnerabilities),
            'low': len([v for v in vulnerabilities if v.severity == 'low']),
            'medium': len([v for v in vulnerabilities if v.severity == 'medium']),
            'high': len([v for v in vulnerabilities if v.severity == 'high'])
        }
        
        # 构建报告数据
        report_data = {
            'scan_id': scan_id,
            'target': scan.target,
            'status': scan.status,
            'created_at': scan.created_at.isoformat(),
            'finished_at': scan.finished_at.isoformat() if scan.finished_at else None,
            'vulnerabilities': vuln_list,
            'risk_stats': risk_stats
        }
        
        # 如果Redis可用且扫描已完成，缓存报告到Redis
        if is_redis_available() and scan.status == 'completed':
            cache_scan_result(scan_id, report_data)
        
        return jsonify(report_data)
        
    except Exception as e:
        logger.error(f"Error getting scan report: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/vuln/<vuln_id>', methods=['GET'])
def get_vulnerability_detail(vuln_id):
    """获取漏洞详情"""
    try:
        # 查询漏洞详情
        vulnerability = Vulnerability.query.get(vuln_id)
        if not vulnerability:
            return jsonify({'error': 'Vulnerability not found'}), 404
        
        # 查询关联的扫描任务
        scan = Scan.query.get(vulnerability.scan_id)
        
        return jsonify({
            'vulnerability': vulnerability.to_dict(),
            'scan_info': {
                'scan_id': scan.id,
                'target': scan.target
            }
        })
        
    except Exception as e:
        logger.error(f"Error getting vulnerability detail: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/attack-path/<scan_id>', methods=['GET'])
def get_attack_path(scan_id):
    """
    获取扫描结果的攻击路径分析
    返回基于NetworkX的攻击图数据，用于前端可视化
    """
    try:
        # 查询扫描任务
        scan = Scan.query.get(scan_id)
        if not scan or scan.status != 'completed':
            return jsonify({'error': 'No completed scan found for this ID'}), 404
        
        # 查询所有漏洞
        vulnerabilities = Vulnerability.query.filter_by(scan_id=scan_id).all()
        
        # 使用攻击路径分析器分析
        attack_path_data = attack_path_analyzer.analyze(vulnerabilities)
        
        # 添加任务信息
        attack_path_data['scan_info'] = {
            'scan_id': scan_id,
            'target': scan.target,
            'scan_time': scan.finished_at.isoformat() if scan.finished_at else None,
            'total_vulnerabilities': len(vulnerabilities)
        }
        
        return jsonify(attack_path_data)
        
    except Exception as e:
        logger.error(f"Error getting attack path: {str(e)}")
        return jsonify({'error': f'Failed to generate attack path: {str(e)}'}), 500

@api_bp.route('/assess-risk', methods=['POST'])
def assess_risk():
    """
    风险评估API端点
    接收漏洞列表，返回风险评估结果
    """
    try:
        # 获取请求数据
        data = request.json
        vulnerabilities = data.get('vulnerabilities', [])
        
        if not vulnerabilities:
            return jsonify({'error': 'Vulnerabilities list is required'}), 400
        
        # 使用风险评估服务生成风险报告
        # 从请求中提取额外信息（如果有）
        scan_info = data.get('scan_info', {})
        assessment_result = risk_assessment_service.generate_risk_report(vulnerabilities, scan_info)
        
        # 构建响应
        return jsonify({
            'success': True,
            'risk_score': assessment_result.get('overall_score', 0),
            'risk_level': assessment_result.get('overall_level', 'unknown'),
            'assessment_details': {
                'severity_distribution': assessment_result.get('severity_distribution', {}),
                'type_distribution': assessment_result.get('type_distribution', {}),
                'total_vulnerabilities': assessment_result.get('total_vulnerabilities', 0),
                'top_risk_factors': assessment_result.get('top_risk_factors', [])
            },
            'recommendations': {
                'summary': assessment_result.get('summary', ''),
                'recommended_fix_order': assessment_result.get('recommended_fix_order', [])
            },
            'confidence_score': assessment_result.get('confidence_score', 0.5)
        }), 200
        
    except Exception as e:
        logger.error(f"Error in risk assessment: {str(e)}")
        return jsonify({'error': f'Risk assessment failed: {str(e)}'}), 500

@api_bp.route('/scan/history', methods=['GET'])
def get_scan_history():
    """获取扫描历史列表"""
    try:
        # 查询所有扫描任务
        scans = Scan.query.order_by(Scan.created_at.desc()).limit(50).all()
        
        # 构建历史数据
        history = []
        for scan in scans:
            # 获取漏洞统计
            vuln_stats = db.session.query(
                Vulnerability.severity,
                db.func.count(Vulnerability.id)
            ).filter_by(scan_id=scan.id).group_by(Vulnerability.severity).all()
            
            stats_dict = dict(vuln_stats)
            risk_stats = {
                'total': sum(stats_dict.values()),
                'low': stats_dict.get('low', 0),
                'medium': stats_dict.get('medium', 0),
                'high': stats_dict.get('high', 0)
            }
            
            history.append({
                'scan_id': scan.id,
                'target': scan.target,
                'status': scan.status,
                'created_at': scan.created_at.isoformat(),
                'finished_at': scan.finished_at.isoformat() if scan.finished_at else None,
                'risk_stats': risk_stats
            })
        
        return jsonify(history)
        
    except Exception as e:
        logger.error(f"Error getting scan history: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/demo/mock_scan', methods=['POST'])
def mock_scan():
    """用于演示的模拟扫描接口，从演示数据文件加载丰富的漏洞数据"""
    try:
        # 获取请求数据
        data = request.json
        target = data.get('target', 'http://example.com')
        
        # 调用服务层函数创建模拟扫描
        result = create_mock_scan(target)
        
        logger.info(f"Mock scan created: {result['scan_id']}, target: {target}")
        
        return jsonify({
            'scan_id': result['scan_id'],
            'target': result['target'],
            'status': 'completed',
            'vulnerabilities': result['vulnerabilities'],
            'risk_stats': result['risk_stats']
        }), 200
        
    except Exception as e:
        logger.error(f"Error in mock scan: {str(e)}")
        return jsonify({'error': f'Failed to create mock scan: {str(e)}'}), 500

# 健康检查端点在app.py中定义，避免重复路由

@api_bp.route('/redis/status', methods=['GET'])
def get_redis_status():
    """Redis状态检查接口"""
    try:
        # 检查Redis连接状态
        redis_available = is_redis_available()
        
        if redis_available:
            # 尝试获取Redis内存信息（简化版）
            try:
                from app.utils.redis_config import get_redis
                redis_client = get_redis()
                info = redis_client.info('memory') if redis_client else {}
                return jsonify({
                    'connected': True,
                    'info': {
                        'used_memory': info.get('used_memory_human', 'unknown'),
                        'max_memory': info.get('maxmemory_human', 'unlimited')
                    }
                }), 200
            except Exception as e:
                logger.warning(f"Failed to get Redis memory info: {str(e)}")
                return jsonify({
                    'connected': True,
                    'info': {
                        'used_memory': 'unknown',
                        'max_memory': 'unknown'
                    }
                }), 200
        else:
            return jsonify({
                'connected': False,
                'info': {}
            }), 200
    except Exception as e:
        logger.error(f"Redis status check failed: {str(e)}")
        return jsonify({
            'connected': False,
            'info': {}
        }), 200

# ===== 靶场管理相关API =====
@api_bp.route('/target-ranges', methods=['POST'])
def create_target_range():
    """创建新的靶场配置"""
    try:
        # 获取请求数据
        data = request.json
        name = data.get('name')
        base_url = data.get('base_url')
        auth_type = data.get('auth_type', 'api_key')
        api_key = data.get('api_key')
        username = data.get('username')
        password = data.get('password')
        description = data.get('description')
        is_active = data.get('is_active', True)
        
        # 验证必填字段
        if not name or not base_url:
            return jsonify({'error': 'Name and base_url are required'}), 400
        
        # 创建新的靶场配置
        target_range = TargetRange(
            name=name,
            base_url=base_url,
            auth_type=auth_type,
            api_key=api_key,
            username=username,
            password=password,
            description=description,
            is_active=is_active
        )
        
        db.session.add(target_range)
        db.session.commit()
        
        logger.info(f"Created target range: {target_range.id}, name: {name}")
        
        return jsonify(target_range.to_dict()), 201
        
    except Exception as e:
        logger.error(f"Error creating target range: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/target-ranges', methods=['GET'])
def get_target_ranges():
    """获取所有靶场配置"""
    try:
        # 查询所有靶场配置
        target_ranges = TargetRange.query.all()
        
        return jsonify([tr.to_dict() for tr in target_ranges]), 200
        
    except Exception as e:
        logger.error(f"Error getting target ranges: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/target-ranges/<target_range_id>', methods=['GET'])
def get_target_range(target_range_id):
    """获取特定靶场配置"""
    try:
        # 查询特定靶场配置
        target_range = TargetRange.query.get(target_range_id)
        if not target_range:
            return jsonify({'error': 'Target range not found'}), 404
        
        return jsonify(target_range.to_dict()), 200
        
    except Exception as e:
        logger.error(f"Error getting target range {target_range_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/target-ranges/<target_range_id>', methods=['PUT'])
def update_target_range(target_range_id):
    """更新特定靶场配置"""
    try:
        # 查询特定靶场配置
        target_range = TargetRange.query.get(target_range_id)
        if not target_range:
            return jsonify({'error': 'Target range not found'}), 404
        
        # 获取请求数据
        data = request.json
        
        # 更新字段
        if 'name' in data:
            target_range.name = data['name']
        if 'base_url' in data:
            target_range.base_url = data['base_url']
        if 'auth_type' in data:
            target_range.auth_type = data['auth_type']
        if 'api_key' in data:
            target_range.api_key = data['api_key']
        if 'username' in data:
            target_range.username = data['username']
        if 'password' in data:
            target_range.password = data['password']
        if 'description' in data:
            target_range.description = data['description']
        if 'is_active' in data:
            target_range.is_active = data['is_active']
        
        db.session.commit()
        
        logger.info(f"Updated target range: {target_range_id}")
        
        return jsonify(target_range.to_dict()), 200
        
    except Exception as e:
        logger.error(f"Error updating target range {target_range_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/target-ranges/<target_range_id>', methods=['DELETE'])
def delete_target_range(target_range_id):
    """删除特定靶场配置"""
    try:
        # 查询特定靶场配置
        target_range = TargetRange.query.get(target_range_id)
        if not target_range:
            return jsonify({'error': 'Target range not found'}), 404
        
        db.session.delete(target_range)
        db.session.commit()
        
        logger.info(f"Deleted target range: {target_range_id}")
        
        return jsonify({'success': True, 'message': 'Target range deleted'}), 200
        
    except Exception as e:
        logger.error(f"Error deleting target range {target_range_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/target-ranges/<target_range_id>/test-connection', methods=['POST'])
def test_target_range_connection(target_range_id):
    """测试与特定靶场的连接"""
    try:
        # 调用服务层测试连接
        result = TargetRangeService.test_connection(target_range_id)
        
        if result['success']:
            return jsonify(result), 200
        else:
            return jsonify(result), 500
        
    except Exception as e:
        logger.error(f"Error testing connection to target range {target_range_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/target-ranges/<target_range_id>/targets', methods=['GET'])
def get_target_range_targets(target_range_id):
    """获取特定靶场中的目标列表"""
    try:
        # 调用服务层获取目标列表
        targets = TargetRangeService.get_targets(target_range_id)
        
        return jsonify(targets), 200
        
    except Exception as e:
        logger.error(f"Error getting targets from target range {target_range_id}: {str(e)}")
        return jsonify({'error': str(e)}), 500

@api_bp.route('/target-ranges/<target_range_id>/scan-results', methods=['POST'])
def submit_target_range_scan_results(target_range_id):
    """向特定靶场提交扫描结果"""
    try:
        # 获取请求数据
        scan_results = request.json
        
        # 调用服务层提交扫描结果
        result = TargetRangeService.submit_scan_results(target_range_id, scan_results)
        
        return jsonify(result), 200
        
    except Exception as e:
        logger.error(f"Error submitting scan results to target range {target_range_id}: {str(e)}")
        return jsonify({'error': str(e)}), 500

@api_bp.route('/target-ranges/<target_range_id>/targets/<target_id>/scan-config', methods=['GET'])
def get_target_range_scan_config(target_range_id, target_id):
    """获取特定靶场中特定目标的扫描配置"""
    try:
        # 调用服务层获取扫描配置
        config = TargetRangeService.get_scan_configuration(target_range_id, target_id)
        
        return jsonify(config), 200
        
    except Exception as e:
        logger.error(f"Error getting scan config from target range {target_range_id}: {str(e)}")
        return jsonify({'error': str(e)}), 500

# ===== 内置靶场相关API =====
@api_bp.route('/target-range/internal/scenarios', methods=['GET'])
def get_internal_scenarios():
    """
    获取所有可用的内置靶场场景
    """
    try:
        scenarios = InternalTargetRangeService.get_available_scenarios()
        return jsonify({
            'success': True,
            'data': scenarios
        })
    except Exception as e:
        logger.error(f"Error getting internal scenarios: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/target-range/internal/scenarios/<scenario_id>/vulnerabilities', methods=['GET'])
def get_scenario_vulnerabilities(scenario_id):
    """
    获取指定场景的漏洞信息
    """
    try:
        if scenario_id not in InternalTargetRangeService.TARGET_SCENARIOS:
            return jsonify({
                'success': False,
                'message': '场景不存在'
            }), 404
        
        vulnerabilities = InternalTargetRangeService.TARGET_SCENARIOS[scenario_id]['vulnerabilities']
        return jsonify({
            'success': True,
            'data': vulnerabilities
        })
    except Exception as e:
        logger.error(f"Error getting scenario vulnerabilities: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/target-range/internal/create', methods=['POST'])
def create_internal_target_range():
    """
    创建内置靶场配置
    """
    try:
        data = request.get_json()
        scenario_id = data.get('scenario_id')
        
        if not scenario_id:
            return jsonify({
                'success': False,
                'message': '场景ID不能为空'
            }), 400
        
        target_range = InternalTargetRangeService.create_target_range_from_scenario(scenario_id, 1)  # 假设默认用户ID为1
        return jsonify({
            'success': True,
            'data': {
                'id': target_range.id,
                'name': target_range.name,
                'base_url': target_range.base_url
            }
        })
    except ValueError as e:
        return jsonify({
            'success': False,
            'message': str(e)
        }), 400
    except Exception as e:
        logger.error(f"Error creating internal target range: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/target-range/internal/simulate-scan', methods=['POST'])
def simulate_internal_scan():
    """
    模拟对靶场的扫描
    """
    try:
        data = request.get_json()
        target_range_id = data.get('target_range_id')
        scan_depth = data.get('scan_depth', 2)
        
        if not target_range_id:
            return jsonify({
                'success': False,
                'message': '靶场ID不能为空'
            }), 400
        
        scan = InternalTargetRangeService.simulate_scan(target_range_id, scan_depth)
        return jsonify({
            'success': True,
            'data': {
                'scan_id': scan.id,
                'target': scan.target
            }
        })
    except ValueError as e:
        return jsonify({
            'success': False,
            'message': str(e)
        }), 400
    except Exception as e:
        logger.error(f"Error simulating internal scan: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/target-range/internal/scenarios/<scenario_id>/scoring-guide', methods=['GET'])
def get_scoring_guide(scenario_id):
    """
    获取靶场评分指南
    """
    try:
        guide = InternalTargetRangeService.get_scoring_guide(scenario_id)
        return jsonify({
            'success': True,
            'data': guide
        })
    except ValueError as e:
        return jsonify({
            'success': False,
            'message': str(e)
        }), 404
    except Exception as e:
        logger.error(f"Error getting scoring guide: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

# ===== 任务调度相关API =====
@api_bp.route('/schedules', methods=['POST'])
def create_schedule():
    """创建新的调度任务"""
    try:
        # 获取请求数据
        data = request.json
        name = data.get('name')
        targets = data.get('targets', [])
        scan_depth = data.get('scan_depth', 2)
        scan_types = data.get('scan_types', ['sql_injection', 'xss', 'info_leak'])
        cron_expression = data.get('cron_expression')
        
        # 调用服务层创建调度任务
        result = ScheduleService.create_schedule(name, targets, scan_depth, scan_types, cron_expression)
        
        logger.info(f"Created schedule: {result['id']}, name: {name}")
        
        return jsonify(result), 201
        
    except ValueError as e:
        logger.error(f"Validation error creating schedule: {str(e)}")
        return jsonify({'error': str(e)}), 400
    except Exception as e:
        logger.error(f"Error creating schedule: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/schedules', methods=['GET'])
def get_schedules():
    """获取所有调度任务"""
    try:
        # 调用服务层获取所有调度任务
        schedules = ScheduleService.get_all_schedules()
        
        return jsonify(schedules), 200
        
    except Exception as e:
        logger.error(f"Error getting schedules: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/schedules/<schedule_id>', methods=['GET'])
def get_schedule(schedule_id):
    """获取特定调度任务"""
    try:
        # 调用服务层获取特定调度任务
        schedule = ScheduleService.get_schedule_by_id(schedule_id)
        
        return jsonify(schedule), 200
        
    except ValueError as e:
        logger.error(f"Schedule not found: {str(e)}")
        return jsonify({'error': str(e)}), 404
    except Exception as e:
        logger.error(f"Error getting schedule {schedule_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/schedules/<schedule_id>', methods=['PUT'])
def update_schedule(schedule_id):
    """更新特定调度任务"""
    try:
        # 获取请求数据
        data = request.json
        
        # 调用服务层更新调度任务
        result = ScheduleService.update_schedule(schedule_id, **data)
        
        logger.info(f"Updated schedule: {schedule_id}")
        
        return jsonify(result), 200
        
    except ValueError as e:
        logger.error(f"Validation error updating schedule {schedule_id}: {str(e)}")
        return jsonify({'error': str(e)}), 400
    except Exception as e:
        logger.error(f"Error updating schedule {schedule_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/schedules/<schedule_id>', methods=['DELETE'])
def delete_schedule(schedule_id):
    """删除特定调度任务"""
    try:
        # 调用服务层删除调度任务
        ScheduleService.delete_schedule(schedule_id)
        
        logger.info(f"Deleted schedule: {schedule_id}")
        
        return jsonify({'success': True, 'message': 'Schedule deleted'}), 200
        
    except ValueError as e:
        logger.error(f"Schedule not found: {str(e)}")
        return jsonify({'error': str(e)}), 404
    except Exception as e:
        logger.error(f"Error deleting schedule {schedule_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/schedules/<schedule_id>/toggle-status', methods=['POST'])
def toggle_schedule_status(schedule_id):
    """切换调度任务的激活状态"""
    try:
        # 调用服务层切换状态
        result = ScheduleService.toggle_schedule_status(schedule_id)
        
        logger.info(f"Toggled schedule status: {schedule_id}, new status: {result['is_active']}")
        
        return jsonify(result), 200
        
    except ValueError as e:
        logger.error(f"Schedule not found: {str(e)}")
        return jsonify({'error': str(e)}), 404
    except Exception as e:
        logger.error(f"Error toggling schedule status {schedule_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/schedules/<schedule_id>/next-runs', methods=['GET'])
def get_next_runs(schedule_id):
    """获取调度任务未来的执行时间"""
    try:
        # 获取参数
        count = request.args.get('count', 5, type=int)
        
        # 调用服务层计算未来执行时间
        next_runs = ScheduleService.calculate_next_run_times(schedule_id, count)
        
        return jsonify({
            'schedule_id': schedule_id,
            'next_runs': next_runs
        }), 200
        
    except ValueError as e:
        logger.error(f"Schedule not found: {str(e)}")
        return jsonify({'error': str(e)}), 404
    except Exception as e:
        logger.error(f"Error calculating next runs for schedule {schedule_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

@api_bp.route('/schedules/<schedule_id>/execute-now', methods=['POST'])
def execute_schedule_now(schedule_id):
    """立即执行调度任务（用于测试）"""
    try:
        # 获取调度任务
        schedule = Schedule.query.get(schedule_id)
        if not schedule:
            return jsonify({'error': 'Schedule not found'}), 404
        
        # 调用服务层执行调度任务
        import json
        from app.services.scan_service import ScanService
        
        targets = json.loads(schedule.targets)
        scan_types = json.loads(schedule.scan_types)
        
        # 为每个目标创建扫描任务
        scan_ids = []
        for target in targets:
            scan_data = {
                'target': target,
                'scan_depth': schedule.scan_depth,
                'scan_types': scan_types,
                'scheduled': True,
                'schedule_id': schedule.id
            }
            scan_service = ScanService()
            scan_id = scan_service.submit_scan(scan_data)
            scan_ids.append(scan_id)
        
        # 更新任务最后执行时间
        from datetime import datetime
        schedule.last_run_at = datetime.utcnow()
        schedule.updated_at = datetime.utcnow()
        db.session.commit()
        
        logger.info(f"Manually executed schedule: {schedule_id}")
        
        return jsonify({
            'success': True,
            'message': 'Schedule executed immediately',
            'scan_ids': scan_ids
        }), 200
        
    except Exception as e:
        logger.error(f"Error executing schedule {schedule_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

# ===== 报告生成和导出相关API =====


@api_bp.route('/scan/<scan_id>/export', methods=['GET'])
def export_vulnerabilities(scan_id):
    """导出漏洞数据（支持多种格式）"""
    try:
        # 获取请求参数
        format_type = request.args.get('format', 'json').lower()
        
        # 调用服务层导出漏洞数据
        export_data, extension, mimetype = ReportService.export_vulnerabilities(scan_id, format_type)
        
        logger.info(f"Exported vulnerabilities for scan {scan_id}, format: {format_type}")
        
        # 设置响应头
        response = make_response(export_data)
        response.headers['Content-Type'] = mimetype
        
        # 设置下载头
        filename = f"vulnerabilities_{scan_id}_{datetime.utcnow().strftime('%Y%m%d%H%M%S')}.{extension}"
        response.headers['Content-Disposition'] = f'attachment; filename={filename}'
        
        return response
        
    except ValueError as e:
        logger.error(f"Validation error exporting vulnerabilities: {str(e)}")
        return jsonify({'error': str(e)}), 400
    except Exception as e:
        logger.error(f"Error exporting vulnerabilities for scan {scan_id}: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

# ===== 漏洞脚本管理相关API =====
@api_bp.route('/scripts', methods=['GET'])
def get_scripts():
    """获取所有脚本列表"""
    try:
        # 获取查询参数
        filter_enabled = request.args.get('filter_enabled', 'true').lower() == 'true'
        
        # 获取脚本列表
        scripts = script_manager.get_scripts(filter_enabled=filter_enabled)
        
        # 转换为可序列化格式
        serializable_scripts = []
        for script in scripts:
            serializable_script = script.copy()
            # 移除不可序列化的字段
            if 'scan_function' in serializable_script:
                del serializable_script['scan_function']
            serializable_scripts.append(serializable_script)
        
        return jsonify({
            'success': True,
            'data': serializable_scripts,
            'total': len(serializable_scripts)
        }), 200
    
    except Exception as e:
        logger.error(f"Error getting scripts: {str(e)}")
        return jsonify({
            'success': False,
            'message': '获取脚本列表失败',
            'error': str(e)
        }), 500

@api_bp.route('/scripts/<script_name>', methods=['GET'])
def get_script(script_name):
    """获取特定脚本详情"""
    try:
        script = script_manager.get_script_by_name(script_name)
        if not script:
            return jsonify({
                'success': False,
                'message': '脚本不存在'
            }), 404
        
        # 转换为可序列化格式
        serializable_script = script.copy()
        if 'scan_function' in serializable_script:
            del serializable_script['scan_function']
        
        return jsonify({
            'success': True,
            'data': serializable_script
        }), 200
    
    except Exception as e:
        logger.error(f"Error getting script {script_name}: {str(e)}")
        return jsonify({
            'success': False,
            'message': '获取脚本详情失败',
            'error': str(e)
        }), 500

@api_bp.route('/scripts', methods=['POST'])
def create_script():
    """创建新脚本"""
    try:
        data = request.json
        script_name = data.get('name')
        content = data.get('content')
        
        if not script_name or not content:
            return jsonify({
                'success': False,
                'message': '脚本名称和内容不能为空'
            }), 400
        
        # 创建脚本
        success = script_manager.create_script(script_name, content)
        if not success:
            return jsonify({
                'success': False,
                'message': '脚本创建失败，可能脚本已存在'
            }), 400
        
        logger.info(f"Created script: {script_name}")
        return jsonify({
            'success': True,
            'message': '脚本创建成功',
            'data': {
                'name': script_name
            }
        }), 201
    
    except Exception as e:
        logger.error(f"Error creating script: {str(e)}")
        return jsonify({
            'success': False,
            'message': '脚本创建失败',
            'error': str(e)
        }), 500

@api_bp.route('/scripts/<script_name>', methods=['PUT'])
def update_script(script_name):
    """更新脚本内容"""
    try:
        data = request.json
        content = data.get('content')
        
        if not content:
            return jsonify({
                'success': False,
                'message': '脚本内容不能为空'
            }), 400
        
        # 更新脚本
        success = script_manager.update_script(script_name, content)
        if not success:
            return jsonify({
                'success': False,
                'message': '脚本更新失败，脚本不存在'
            }), 404
        
        logger.info(f"Updated script: {script_name}")
        return jsonify({
            'success': True,
            'message': '脚本更新成功',
            'data': {
                'name': script_name
            }
        }), 200
    
    except Exception as e:
        logger.error(f"Error updating script {script_name}: {str(e)}")
        return jsonify({
            'success': False,
            'message': '脚本更新失败',
            'error': str(e)
        }), 500

@api_bp.route('/scripts/<script_name>', methods=['DELETE'])
def delete_script(script_name):
    """删除脚本"""
    try:
        # 删除脚本
        success = script_manager.delete_script(script_name)
        if not success:
            return jsonify({
                'success': False,
                'message': '脚本删除失败，脚本不存在'
            }), 404
        
        logger.info(f"Deleted script: {script_name}")
        return jsonify({
            'success': True,
            'message': '脚本删除成功'
        }), 200
    
    except Exception as e:
        logger.error(f"Error deleting script {script_name}: {str(e)}")
        return jsonify({
            'success': False,
            'message': '脚本删除失败',
            'error': str(e)
        }), 500

@api_bp.route('/scripts/<script_name>/toggle-status', methods=['POST'])
def toggle_script_status(script_name):
    """启用或禁用脚本"""
    try:
        data = request.json
        enabled = data.get('enabled')
        
        if enabled is None:
            return jsonify({
                'success': False,
                'message': '启用状态参数不能为空'
            }), 400
        
        # 切换脚本状态
        success = script_manager.toggle_script_status(script_name, enabled)
        if not success:
            return jsonify({
                'success': False,
                'message': '切换脚本状态失败，脚本不存在'
            }), 404
        
        logger.info(f"Toggled script status: {script_name}, enabled: {enabled}")
        return jsonify({
            'success': True,
            'message': '脚本已启用' if enabled else '脚本已禁用',
            'data': {
                'name': script_name,
                'enabled': enabled
            }
        }), 200
    
    except Exception as e:
        logger.error(f"Error toggling script status {script_name}: {str(e)}")
        return jsonify({
            'success': False,
            'message': '切换脚本状态失败',
            'error': str(e)
        }), 500

@api_bp.route('/scripts/template', methods=['GET'])
def get_script_template():
    """获取脚本模板"""
    try:
        # 获取查询参数
        script_name = request.args.get('name', 'new_scan_script')
        vuln_type = request.args.get('type', 'custom')
        
        # 获取模板
        template = script_manager.get_script_template(script_name, vuln_type)
        
        return jsonify({
            'success': True,
            'data': {
                'template': template
            }
        }), 200
    
    except Exception as e:
        logger.error(f"Error getting script template: {str(e)}")
        return jsonify({
            'success': False,
            'message': '获取脚本模板失败',
            'error': str(e)
        }), 500

@api_bp.route('/scripts/execute', methods=['POST'])
def execute_script():
    """执行指定脚本（用于测试）"""
    try:
        data = request.json
        script_name = data.get('script_name')
        target = data.get('target')
        params = data.get('params', {})
        
        if not script_name or not target:
            return jsonify({
                'success': False,
                'message': '脚本名称和目标不能为空'
            }), 400
        
        # 执行脚本
        result = script_manager.execute_script(script_name, target, **params)
        if result is None:
            return jsonify({
                'success': False,
                'message': '脚本执行失败，脚本不存在或已禁用'
            }), 400
        
        logger.info(f"Executed script: {script_name} on target: {target}")
        return jsonify({
            'success': True,
            'message': '脚本执行成功',
            'data': result
        }), 200
    
    except Exception as e:
        logger.error(f"Error executing script: {str(e)}")
        return jsonify({
            'success': False,
            'message': '脚本执行失败',
            'error': str(e)
        }), 500

@api_bp.route('/report/templates', methods=['GET'])
def get_report_templates():
    """
    获取可用的报告模板列表
    """
    try:
        # 调用服务层获取报告模板列表
        templates = ReportService.get_report_templates()
        
        return jsonify({
            'templates': templates
        }), 200
        
    except Exception as e:
        logger.error(f"Error getting report templates: {str(e)}")
        return jsonify({'error': 'Internal server error'}), 500

# ===== 漏洞统计分析相关API =====
@api_bp.route('/statistics/summary', methods=['GET'])
def get_vulnerability_summary():
    """
    获取漏洞统计摘要
    """
    try:
        start_date = request.args.get('start_date')
        end_date = request.args.get('end_date')
        user_id = request.args.get('user_id', type=int)
        
        # 解析日期
        if start_date:
            start_date = datetime.fromisoformat(start_date)
        if end_date:
            end_date = datetime.fromisoformat(end_date)
        
        summary = VulnerabilityStatsService.get_vulnerability_summary(
            start_date, end_date, user_id
        )
        
        return jsonify({
            'success': True,
            'data': summary
        })
    except Exception as e:
        logger.error(f"Error getting vulnerability summary: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/statistics/target/<path:target_url>', methods=['GET'])
def get_target_statistics(target_url):
    """
    获取特定目标的漏洞统计
    """
    try:
        user_id = request.args.get('user_id', type=int)
        
        stats = VulnerabilityStatsService.get_target_vulnerability_stats(
            target_url, user_id
        )
        
        return jsonify({
            'success': True,
            'data': stats
        })
    except Exception as e:
        logger.error(f"Error getting target statistics: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/statistics/risk-assessment', methods=['GET'])
def get_risk_assessment_statistics():
    """
    获取风险评估统计
    """
    try:
        user_id = request.args.get('user_id', type=int)
        
        assessment = VulnerabilityStatsService.get_risk_assessment_summary(user_id)
        
        return jsonify({
            'success': True,
            'data': assessment
        })
    except Exception as e:
        logger.error(f"Error getting risk assessment statistics: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/statistics/remediation-progress', methods=['GET'])
def get_remediation_progress():
    """
    获取修复进度统计
    """
    try:
        start_date = request.args.get('start_date')
        end_date = request.args.get('end_date')
        user_id = request.args.get('user_id', type=int)
        
        # 解析日期
        if start_date:
            start_date = datetime.fromisoformat(start_date)
        if end_date:
            end_date = datetime.fromisoformat(end_date)
        
        progress = VulnerabilityStatsService.get_remediation_progress(
            start_date, end_date, user_id
        )
        
        return jsonify({
            'success': True,
            'data': progress
        })
    except Exception as e:
        logger.error(f"Error getting remediation progress: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/statistics/export', methods=['GET'])
def export_statistics():
    """
    导出统计数据为JSON
    """
    try:
        start_date = request.args.get('start_date')
        end_date = request.args.get('end_date')
        user_id = request.args.get('user_id', type=int)
        
        # 解析日期
        if start_date:
            start_date = datetime.fromisoformat(start_date)
        if end_date:
            end_date = datetime.fromisoformat(end_date)
        
        json_data = VulnerabilityStatsService.export_statistics_to_json(
            start_date, end_date, user_id
        )
        
        filename = f"vulnerability_statistics_{datetime.utcnow().strftime('%Y%m%d_%H%M%S')}.json"
        
        return Response(
            json_data,
            mimetype='application/json',
            headers={
                'Content-Disposition': f'attachment; filename={filename}'
            }
        )
    except Exception as e:
        logger.error(f"Error exporting statistics: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

# ===== 漏洞管理相关API =====
@api_bp.route('/vulnerabilities', methods=['GET'])
def get_vulnerabilities():
    """
    获取漏洞列表（支持分页和筛选）
    """
    try:
        # 获取查询参数
        page = request.args.get('page', 1, type=int)
        page_size = request.args.get('page_size', 10, type=int)
        severity = request.args.get('severity')
        status = request.args.get('status')
        vuln_type = request.args.get('vuln_type')
        search = request.args.get('search')
        sort_by = request.args.get('sort_by', 'created_at')
        sort_order = request.args.get('sort_order', 'desc')
        
        # 构建查询
        query = Vulnerability.query
        
        # 应用筛选条件
        if severity:
            query = query.filter_by(severity=severity)
        if status:
            query = query.filter_by(status=status)
        if vuln_type:
            query = query.filter_by(vuln_type=vuln_type)
        if search:
            # 搜索漏洞ID、类型、路径等
            search_pattern = f"%{search}%"
            query = query.filter(
                db.or_(
                    Vulnerability.vuln_id.like(search_pattern),
                    Vulnerability.vuln_type.like(search_pattern),
                    Vulnerability.path.like(search_pattern)
                )
            )
        
        # 应用排序
        if hasattr(Vulnerability, sort_by):
            sort_column = getattr(Vulnerability, sort_by)
            if sort_order == 'desc':
                sort_column = sort_column.desc()
            query = query.order_by(sort_column)
        else:
            # 默认按创建时间排序
            query = query.order_by(Vulnerability.created_at.desc())
        
        # 分页
        pagination = query.paginate(page=page, per_page=page_size, error_out=False)
        
        # 转换为字典格式
        vulnerabilities = [v.to_dict() for v in pagination.items]
        
        # 获取统计信息
        total_count = pagination.total
        severity_stats = db.session.query(
            Vulnerability.severity,
            db.func.count(Vulnerability.id)
        ).group_by(Vulnerability.severity).all()
        
        status_stats = db.session.query(
            Vulnerability.status,
            db.func.count(Vulnerability.id)
        ).group_by(Vulnerability.status).all()
        
        return jsonify({
            'success': True,
            'data': {
                'vulnerabilities': vulnerabilities,
                'pagination': {
                    'current_page': page,
                    'page_size': page_size,
                    'total_pages': pagination.pages,
                    'total_items': total_count
                },
                'statistics': {
                    'severity_distribution': dict(severity_stats),
                    'status_distribution': dict(status_stats)
                }
            }
        })
    except Exception as e:
        logger.error(f"Error getting vulnerabilities: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/vulnerabilities/<vuln_id>/status', methods=['PUT'])
def update_vulnerability_status(vuln_id):
    """
    更新单个漏洞状态
    """
    try:
        # 获取漏洞
        vulnerability = Vulnerability.query.get(vuln_id)
        if not vulnerability:
            return jsonify({
                'success': False,
                'message': '漏洞不存在'
            }), 404
        
        # 获取请求数据
        data = request.json
        new_status = data.get('status')
        
        # 验证状态值
        valid_statuses = ['unhandled', 'confirmed', 'in_progress', 'fixed', 'verified']
        if new_status not in valid_statuses:
            return jsonify({
                'success': False,
                'message': f'无效的状态值。有效值为: {valid_statuses}'
            }), 400
        
        # 更新状态
        vulnerability.status = new_status
        vulnerability.updated_at = datetime.utcnow()
        db.session.commit()
        
        logger.info(f"Updated vulnerability status: {vuln_id}, new status: {new_status}")
        
        return jsonify({
            'success': True,
            'data': vulnerability.to_dict()
        })
    except Exception as e:
        db.session.rollback()
        logger.error(f"Error updating vulnerability status: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/vulnerabilities/batch/status', methods=['PUT'])
def batch_update_vulnerability_status():
    """
    批量更新漏洞状态
    """
    try:
        # 获取请求数据
        data = request.json
        vuln_ids = data.get('vuln_ids', [])
        new_status = data.get('status')
        
        if not vuln_ids:
            return jsonify({
                'success': False,
                'message': '漏洞ID列表不能为空'
            }), 400
        
        # 验证状态值
        valid_statuses = ['unhandled', 'confirmed', 'in_progress', 'fixed', 'verified']
        if new_status not in valid_statuses:
            return jsonify({
                'success': False,
                'message': f'无效的状态值。有效值为: {valid_statuses}'
            }), 400
        
        # 更新漏洞状态
        updated_count = Vulnerability.query.filter(
            Vulnerability.id.in_(vuln_ids)
        ).update(
            {'status': new_status, 'updated_at': datetime.utcnow()},
            synchronize_session=False
        )
        
        db.session.commit()
        
        logger.info(f"Batch updated {updated_count} vulnerabilities to status: {new_status}")
        
        return jsonify({
            'success': True,
            'data': {
                'updated_count': updated_count,
                'status': new_status
            }
        })
    except Exception as e:
        db.session.rollback()
        logger.error(f"Error batch updating vulnerability status: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/vulnerabilities/<vuln_id>', methods=['DELETE'])
def delete_vulnerability(vuln_id):
    """
    删除单个漏洞
    """
    try:
        # 获取漏洞
        vulnerability = Vulnerability.query.get(vuln_id)
        if not vulnerability:
            return jsonify({
                'success': False,
                'message': '漏洞不存在'
            }), 404
        
        # 删除漏洞
        db.session.delete(vulnerability)
        db.session.commit()
        
        logger.info(f"Deleted vulnerability: {vuln_id}")
        
        return jsonify({
            'success': True,
            'message': '漏洞删除成功'
        })
    except Exception as e:
        db.session.rollback()
        logger.error(f"Error deleting vulnerability: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/vulnerabilities/batch/delete', methods=['DELETE'])
def batch_delete_vulnerabilities():
    """
    批量删除漏洞
    """
    try:
        # 获取请求数据
        data = request.json
        vuln_ids = data.get('vuln_ids', [])
        
        if not vuln_ids:
            return jsonify({
                'success': False,
                'message': '漏洞ID列表不能为空'
            }), 400
        
        # 删除漏洞
        deleted_count = Vulnerability.query.filter(
            Vulnerability.id.in_(vuln_ids)
        ).delete(synchronize_session=False)
        
        db.session.commit()
        
        logger.info(f"Batch deleted {deleted_count} vulnerabilities")
        
        return jsonify({
            'success': True,
            'data': {
                'deleted_count': deleted_count
            }
        })
    except Exception as e:
        db.session.rollback()
        logger.error(f"Error batch deleting vulnerabilities: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

# 脚本管理相关API端点
@api_bp.route('/scripts', methods=['GET'])
def get_scripts():
    """
    获取所有脚本列表
    """
    try:
        # 获取查询参数
        enabled = request.args.get('enabled', None)
        
        # 加载脚本（确保获取最新的脚本列表）
        script_manager.load_scripts()
        
        # 根据参数筛选脚本
        scripts = script_manager.get_scripts(filter_enabled=(enabled != 'false'))
        
        # 转换为可序列化的格式
        scripts_data = []
        for script in scripts:
            script_dict = {
                'id': script['name'],
                'name': script['name'],
                'description': script['description'],
                'type': script['vulnerability_type'],
                'severity': script['severity'],
                'enabled': script['enabled'],
                'author': script['author'],
                'version': script['version']
            }
            scripts_data.append(script_dict)
        
        return jsonify({
            'success': True,
            'data': scripts_data
        })
    except Exception as e:
        logger.error(f"Error getting scripts: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/scripts/<script_id>', methods=['GET'])
def get_script_detail(script_id):
    """
    获取脚本详情
    """
    try:
        script = script_manager.get_script_by_name(script_id)
        if not script:
            return jsonify({
                'success': False,
                'message': '脚本不存在'
            }), 404
        
        # 读取脚本文件内容
        with open(script['path'], 'r', encoding='utf-8') as f:
            content = f.read()
        
        script_data = {
            'id': script['name'],
            'name': script['name'],
            'description': script['description'],
            'type': script['vulnerability_type'],
            'severity': script['severity'],
            'enabled': script['enabled'],
            'author': script['author'],
            'version': script['version'],
            'content': content,
            'required_params': script['required_params'],
            'optional_params': script['optional_params']
        }
        
        return jsonify({
            'success': True,
            'data': script_data
        })
    except Exception as e:
        logger.error(f"Error getting script detail: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/scripts', methods=['POST'])
def create_script():
    """
    创建新脚本
    """
    try:
        data = request.json
        script_name = data.get('name')
        content = data.get('content')
        
        if not script_name or not content:
            return jsonify({
                'success': False,
                'message': '脚本名称和内容不能为空'
            }), 400
        
        # 验证脚本内容
        is_valid, message = script_manager.validate_script(content)
        if not is_valid:
            return jsonify({
                'success': False,
                'message': message
            }), 400
        
        # 创建脚本
        success = script_manager.create_script(script_name, content)
        if not success:
            return jsonify({
                'success': False,
                'message': '脚本创建失败'
            }), 500
        
        return jsonify({
            'success': True,
            'message': '脚本创建成功'
        })
    except Exception as e:
        logger.error(f"Error creating script: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/scripts/<script_id>', methods=['PUT'])
def update_script(script_id):
    """
    更新脚本
    """
    try:
        data = request.json
        content = data.get('content')
        
        if not content:
            return jsonify({
                'success': False,
                'message': '脚本内容不能为空'
            }), 400
        
        # 验证脚本内容
        is_valid, message = script_manager.validate_script(content)
        if not is_valid:
            return jsonify({
                'success': False,
                'message': message
            }), 400
        
        # 更新脚本
        success = script_manager.update_script(script_id, content)
        if not success:
            return jsonify({
                'success': False,
                'message': '脚本更新失败'
            }), 500
        
        return jsonify({
            'success': True,
            'message': '脚本更新成功'
        })
    except Exception as e:
        logger.error(f"Error updating script: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/scripts/<script_id>', methods=['DELETE'])
def delete_script(script_id):
    """
    删除脚本
    """
    try:
        success = script_manager.delete_script(script_id)
        if not success:
            return jsonify({
                'success': False,
                'message': '脚本删除失败'
            }), 500
        
        return jsonify({
            'success': True,
            'message': '脚本删除成功'
        })
    except Exception as e:
        logger.error(f"Error deleting script: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/scripts/<script_id>/status', methods=['PUT'])
def toggle_script_status(script_id):
    """
    启用或禁用脚本
    """
    try:
        data = request.json
        enabled = data.get('enabled')
        
        if enabled is None:
            return jsonify({
                'success': False,
                'message': '必须指定启用状态'
            }), 400
        
        success = script_manager.toggle_script_status(script_id, enabled)
        if not success:
            return jsonify({
                'success': False,
                'message': '脚本状态更新失败'
            }), 500
        
        return jsonify({
            'success': True,
            'message': '脚本已{}'.format('启用' if enabled else '禁用')
        })
    except Exception as e:
        logger.error(f"Error toggling script status: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/scripts/upload', methods=['POST'])
def upload_script():
    """
    上传脚本文件
    """
    try:
        # 检查是否有文件
        if 'file' not in request.files:
            return jsonify({
                'success': False,
                'message': '未找到文件'
            }), 400
        
        file = request.files['file']
        
        # 检查文件名
        if not file.filename.endswith('.py'):
            return jsonify({
                'success': False,
                'message': '只支持Python文件(.py)'
            }), 400
        
        # 读取文件内容
        content = file.read().decode('utf-8')
        
        # 获取脚本名称（去掉.py扩展名）
        script_name = file.filename[:-3]
        
        # 验证脚本内容
        is_valid, message = script_manager.validate_script(content)
        if not is_valid:
            return jsonify({
                'success': False,
                'message': message
            }), 400
        
        # 检查脚本是否已存在
        existing_script = script_manager.get_script_by_name(script_name)
        if existing_script:
            # 更新现有脚本
            success = script_manager.update_script(script_name, content)
        else:
            # 创建新脚本
            success = script_manager.create_script(script_name, content)
        
        if not success:
            return jsonify({
                'success': False,
                'message': '脚本上传失败'
            }), 500
        
        return jsonify({
            'success': True,
            'message': '脚本{}成功'.format('更新' if existing_script else '上传')
        })
    except Exception as e:
        logger.error(f"Error uploading script: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/scripts/template', methods=['GET'])
def get_script_template():
    """
    获取脚本模板
    """
    try:
        script_name = request.args.get('name', 'new_script')
        vuln_type = request.args.get('type', 'general')
        
        template = script_manager.get_script_template(script_name, vuln_type)
        
        return jsonify({
            'success': True,
            'data': {
                'template': template
            }
        })
    except Exception as e:
        logger.error(f"Error getting script template: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/scripts/batch/status', methods=['PUT'])
def batch_toggle_script_status():
    """
    批量启用或禁用脚本
    """
    try:
        data = request.json
        script_ids = data.get('script_ids', [])
        enabled = data.get('enabled')
        
        if not script_ids:
            return jsonify({
                'success': False,
                'message': '脚本ID列表不能为空'
            }), 400
        
        if enabled is None:
            return jsonify({
                'success': False,
                'message': '必须指定启用状态'
            }), 400
        
        success_count = 0
        failed_count = 0
        failed_scripts = []
        
        for script_id in script_ids:
            success = script_manager.toggle_script_status(script_id, enabled)
            if success:
                success_count += 1
            else:
                failed_count += 1
                failed_scripts.append(script_id)
        
        return jsonify({
            'success': True,
            'data': {
                'success_count': success_count,
                'failed_count': failed_count,
                'failed_scripts': failed_scripts
            },
            'message': '成功{}{}个脚本'.format('启用' if enabled else '禁用', success_count)
        })
    except Exception as e:
        logger.error(f"Error batch toggling script status: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500

@api_bp.route('/scripts/batch/delete', methods=['DELETE'])
def batch_delete_scripts():
    """
    批量删除脚本
    """
    try:
        data = request.json
        script_ids = data.get('script_ids', [])
        
        if not script_ids:
            return jsonify({
                'success': False,
                'message': '脚本ID列表不能为空'
            }), 400
        
        success_count = 0
        failed_count = 0
        failed_scripts = []
        
        for script_id in script_ids:
            success = script_manager.delete_script(script_id)
            if success:
                success_count += 1
            else:
                failed_count += 1
                failed_scripts.append(script_id)
        
        return jsonify({
            'success': True,
            'data': {
                'success_count': success_count,
                'failed_count': failed_count,
                'failed_scripts': failed_scripts
            },
            'message': f'成功删除{success_count}个脚本'
        })
    except Exception as e:
        logger.error(f"Error batch deleting scripts: {str(e)}")
        return jsonify({
            'success': False,
            'message': str(e)
        }), 500